COOLjsMenu: Introduction and Manual Reference

Foreword

This document covers most of the creation and initialization process for COOLjsMenu and COOLjsMenu Professional from CoolDev.Com. While this document describes data structures needed by these scripts and the way all these things can be glued together to fit in your pages, you will not find wide variety of complete samples here: you can find them in your COOLjsMenu or COOLjsMenu Professional package in the "demos" or "samples" subdirectories. Also, this document does not cover license, support and purchase issues - answers to these questions you can find in the FAQ.

COOLjsMenu Professional has all the functions that are included in COOLjsMenu, and offers many additional, but generally scripts are compatible. Input data and format specifications for both these scripts are very alike, and all farther references to "menu" will mean both COOLjsMenu and COOLjsMenu Professional if not specified otherwise.

Authors

Author of this document is Alex Kunin, representative of CoolDev.com technical support team. If you have comments, questions, brilliant ideas, more brilliant ideas, or you want to criticize something then don't hesitate contacting me at javascript@cooldev.com.

Contents

  1. General information
  2. Required components and installation process
  3. Complete samples
  4. Menu definition file format

General information

Scripts covered in this document allow you to create and use menu-like visual representation of hierarchical data - most close analogies are menu bar and popup menu which can be found in almost every visual application. The most natural way to use these scripts is to build site navigation system, but there are some other variants how menus can be used: context menus, rollover-enabled buttons, compact document outline, etc. Galleries of samples for the COOLjsMenu and COOLjsMenu Professional are available online - they will help you to get general idea of the possibilities that menu provides.

Basically menu is a program written in JavaScript - programming language commonly used in web development. No JavaScript knowledge is required to use the menu - this is not too hard to modify existing sample (e.g. complete sample which is explained in this document) to get working menu which will suit your needs. But for advanced menu usage it is strongly recommended to have basic JavaScript skills.

To create and test menu you need some text editor and some browser. Menu runs on most of the available browsers that provide JavaScript and CSS support. These browsers are: Internet Explorer 4 and above, Netscape Navigator 4.x, Netscape Navigator 6 and above, Mozilla 0.9.4 and above, Opera 5 and above. To create and/or modify menu definition you need some text editor (Notepad for Windows' users is a good one to start). More complex systems for site management such as FrontPage, InterDev, and Dreamweaver also can be used.

Required components and installation process

To get the menu working you need following components:

  • menu script itself (coolmenu.js or coolmenupro.js; these files are can be found in the "js" subdirectory in the corresponding packages);
  • menu structure definition - captions and URLs for every item, styles, position, offsets, sizes, etc.;
  • HTML page which will include the menu.

You can place these components into separate files (next section tells how to do this) or put them into a single HTML document. No matter what way you will choose initialization sequence must be in the HTML code. This sequence is different for COOLjsMenu and COOLjsMenu Professional.

COOLjsMenu's initialization sequence presented below.

<script type="text/javascript">
var myMenu = new COOLjsMenu("menu1", MENU_ITEMS);
</script>

This code snippet must be placed somewhere in the HTML code, but not inside any containers other than <BODY> - this is very important. By not following this rule you'll get displaced submenus. The best place for this code is immediately before the closing </BODY> tag - it is safe to place initialization there. (Technical details: COOLjsMenu's constructor will generate HTML code - set of DIVs, and then this code will be written to the document flow using "document.write()" method. So, putting the constructor call in a wrong place will lead to undesirable side effects.)

Initialization sequence for COOLjsMenu Professional looks like the this:

var myMenu = new COOLjsMenuPRO("menu1", MENU_ITEMS);
</script>
...
<script type="text/javascript">
myMenu.initTop();
</script>
...
<script type="text/javascript">
CLoadNotify();
</script>
</body>
</html>

As you can see code contains three custom elements (this applies to both COOLjsMenu and COOLjsMenu Professional):

  • myMenu - name of the variable that will hold reference to the newly created menu; this variable can be used to access menu at runtime, e.g. to hide or show submenus or to set up event handlers;
  • "menu1" - name of the menu; if you have several menus on the page then you have to name them differently, e.g. "menu1", "menu2" and so on; it is recommended to compose these names using alphanumeric characters because there are many places where names will be used: CSS class names, images' and layers' identifiers - some browsers do not allow to have fancy symbols here (e.g. Opera 5 does not understand CSS class names with underscores); it's Ok if menu name and menu variable name will match;
  • MENU_ITEMS - JavaScript array with items (you can find sample farther in this section, reference is in the corresponding section); because this is a JavaScript construct it's definition must be placed into <SCRIPT> tag or into the separate .js file.

COOLjsMenu Professional has couple of additional initialization statements (see Fig. 2). If your menu is positioned absolutely (see "Menu definition file format" reference for details) then you can place all these code pieces into single <SCRIPT> statement just before the </BODY> - outside of any containers. For relative positioning mode following rules must be honored: "new COOLjsMenuPRO(...)" part can be placed anywhere before the "initTop()"; at the place where you want to see your menu (e.g. inside a TD cell) "initTop()" part must be placed; "init()" and "draw()" should be at the very end of file before the closing </BODY> tag.

Here is minimum HTML document with COOLjsTree inside:

<html>
    <head>
        <script type="text/javascript" src="coolmenu.js"></script>
    </head>
    <body>
        <script type="text/javascript">
// Part 1 - Styles
var STYLE = {
    border:1,              // item's border width, pixels; zero means "none";
    shadow:2,              // item's shadow size, pixels; zero means "none"
    color:{
        border:"#666666",  // color of the item border, if any;
        shadow:"#DBD8D1",  // color of the item shadow, if any;
        bgON:"white",      // background color for the items;
        bgOVER:"#B6BDD2"   // background color for the item
                           // which is under mouse right now;
    },
    css:{
        ON:null,           // CSS class for items;
        OVER:null          // CSS class  for item which is under mouse;
    }
};

// Part 2 - Menu structure
var MENU_ITEMS = [
    {pos:[10,10], itemoff:[0,99], leveloff:[21,0], style:STYLE, size:[22,100]},
    {code:"Item 1", url:"item1.html",
        sub:[
            {"itemoff":[21,0]},
            {code:"SubItem 1", "url":"subitem1_1.html"},
            {code:"SubItem 2", "url":"subitem1_2.html"},
            {code:"SubItem 3", "url":"subitem1_3.html"},
            {code:"SubItem 4", "url":"subitem1_4.html"}
        ]
    },
    {code:"Item 2", url:"item2.html",
        sub:[
            {itemoff:[21,0]},
            {code:"SubItem 1", "url":"subitem2_1.html"},
            {code:"SubItem 2", "url":"subitem2_2.html"},
            {code:"SubItem 3", "url":"subitem2_3.html"},
            {code:"SubItem 4", "url":"subitem2_4.html"}
        ]
    }
];

// Part 3 - Initialization code
var m1 = new COOLjsMenu("menu1", MENU_ITEMS);
                </script>
        </body>
</html>

Initialization sequence is denoted by blue background. Menu definition has been split into two parts - style definition (red border) and structure definition (green border). That was done only for convenience, and piece of code which references style definition can be solid:

var MENU_ITEMS = [
    {
        pos:[10,10],
        itemoff:[0,99],
        leveloff:[21,0],
        style:{
            border:1,
            shadow:2,
            color:{
                border:"#666666",
                shadow:"#DBD8D1",
                bgON:"white",
                bgOVER:"#B6BDD2"
            },
            css:{
                ON:"clsCMOn",
                OVER:"clsCMOver"
            }
        },
        size:[22,100]
    },
    {code:"Item 1", url:"item1.html",
    ...
];

But average menu usually contains more than one style, and there can be more then one reference to the same style. So, to have clean, non-garbled code we recommend you to split styles and structure.

COOLjsMenu Professional has same inclusion scheme, but with some additional statements in the initialization sequence:

var m1 = new COOLjsMenuPRO("menu1", MENU_ITEMS);
m1.initTop();
CLoadNotify();

Style definitions and structure definitions are basically the same. Detailed information about style and structure definitions are given in the "Reference" section.

Note about CLoadNotify: it is needed to activate the menu, to show it the very first time. This call is optional, you can safely skip it because menu will be activated when the page will be loaded. But if your page contains lots of graphics (especially things like banners which are hosted on other domains and generate several HTTP requests), then there might be a significant delay between two events: “HTML loaded” and “page loaded”. Menu can be activated when HTML is fully loaded, but there is no standard way to catch this moment. This is why we need to call some custom function (CLoadNotify) which will notify all menu scripts that it is time to appear.

Complete samples

If you plan to include same menu into many pages from your site then it is good idea to split samples from previous section into several files. Here is typical set of files:

  • menuitems.js - contains MENU_ITEMS variable - menu's styles and structure;
  • style.css - CSS classes for the menu;
  • coolmenu.js or coolmenupro.js - the menu itself;
  • images - your menu will contain at least blank 1x1 image (it is used internally by the script), and also there can be additional images like icons and arrows.

Some HTML code is also needed, of course.

Here are two complete samples which contain all the files listed above: COOLjsMenu and COOLjsMenu Professional. These are good points to start from: .js files are commented, and you will not get lost. So, download these .zip files, unpack them somewhere, add coolmenu.js and coolmenupro.js, and then run the samples.

Menu definition file format

Menu definition file format consists of two parts: styles and structure.

// styles
var STYLE1 = {
    border:1,
    ...
};

var STYLE2 = {
    border:1,
    ...
};

// structure
var MENU_ITEMS = [
    {pos:'relative', style:STYLE1, ...},
    {code:'Item 1', ...},
    ...
];

"MENU_ITEMS" is the name of the variable which holds full menu definition - that name will be used during menu initialization. Style names "STYLE1", "STYLE2" will be used only within menu definition file. Styles' definition are separated from the structure only for convenience - "MENU_ITEMS" actually holds united array of styles and structure.

Style definition

Menu style defines colors for item background (1), shadow (2), border (3), icon background (4). Also, it defines colors for item and icon backgrounds in rollovered state, size of the shadow and border, and CSS classes for the item's text in rollovered state.

Here is typical style definition:

var STYLE1 = {
    border:1,
    borders:[1,1,2,1],
    shadow:2,
    color:{
        border:"#666666",
        shadow:"#DBD8D1",
        bgON:"white",
        bgOVER:"#B6BDD2",
        imagebg:'silver',
        oimagebg:'black'
    },
    css:{
        ON:"clsCMOn",
        OVER:"clsCMOver"
    }
};

Style definition's fields have following meanings:

Name State aware? * Description
leveloff  

Specifies distance between top-left corner of the item and it's submenu. Following code will make submenu appear under the item:

leveloff:[20,0]
size  

Defines item's size, e.g. item size 100x20 pixels will look like this:

size:[20,100]
itemoff  

Specifies distance between top-left corners of the neighbor items. Horizontal offset - 10 pixels, vertical offset - 5 pixels:

itemoff:[5,10]
backgroundColor Yes

Specifies background color for the item:

backgroundColor:'silver'
color.bgON, color.bgOVER   Obsolete way to use "backgroundColor".
backgroundStyle Yes

Specifies CSS style for the item's background layer:

backgroundStyle:'background: url(pic.gif);'
textClass Yes

Specifies CSS class for the item's text layer:

textClass:'menuTextClass'
css.ON, css.OVER   Obsolete way to use "textClass".
borderColor  

Specifies color for the item's border:

borderColor:'#F0F0F0'
borderWidth  

Specifies width in pixels for the item's border:

borderWidth:3
Professional edition also can accept array of the following format: [ left, top, right, bottom ].
borderWidth:[4,5,6,7]
border, borders   Obsolete way to use "borderWidth".
shadowColor  

Defines shadow's color.

shadow  

Specifies shadow size, in pixels. May accept one (vertical and horizontal sizes are equal) or two (vertical and horizontal are not equal) numbers. Numbers can be positive (right or down direction) or negative (left or up direction)

shadow:3
shadow:[1,2]
shadow:[-2,2]
valign Yes

Same as TD's "valign" attribute. Affects item's contents: text, icon, arrow.

backgroundClass Yes

Specifies CSS class for the item's background layer:

backgroundClass:'menuBackgroundClass'
textStyle Yes

Specifies CSS style for the item's text layer:

textStyle:'font: 11px Verdana; color: blue;'
itemFilters  

Adds 'filter' style definitions to item**. Has not effect in browsers other than Internet Explorer.

levelFilters  

Adds 'filter' style definitions to level**. Has not effect in browsers other than Internet Explorer.

transparentBorder  

Setting this field to "true" will make real borders. This is useful only if transparency is used.

Note: this option increases number of layers, and menu can run a bit slower.

measureRollover  

When autosize is in use, item's dimensions depend on text layer size. This is OK for most cases, but if rollover state's text layer is larger (e.g. font in rollovered state is bold), it will go out of bounds. To overcome this problem, set measureRollover to true.

image Yes

Professional edition only. Defines icon image; imgsize:[height, width] is mandatory, it specifies size of the icon.

image:[ 'icon1_normal.gif', 'icon1_rollover.gif' ], imgsize:[10,15]

To stop inheritance, you can specify "null" value:

image:null

Image will be aligned to the left side of the item. If you want to have item with no text, but with image, then you can use item's "code" field with <img src="..."> tag inside.

oimage   Obsolete way to use "image".
imgsize   See "image" above.
arrow Yes Same as "image", but defines arrow image which is visible only if item has submenu. Arrow will be right-aligned.
oarrow   Obsolete way to use "arrow".
arrsize   See "image" and "arrow" above.
ifFirst  

This field can contain any other style fields, but they will apply to the first item only. Other "if*" fields are not allowed here.

textStyle:'color:red;',
backgroundColor:'silver',
ifFirst:{
    textStyle:'color:blue'
}

Applyting sample style above will assign "silver" as background color for every item, "blue" as foreground color for the first item, and "red" as foreground color for other items. Note that background color will be used in both cases, and only foreground color will be overriden for the first item.

ifLast   Same as "ifFirst" above, but sub-style will be applied to the last item only.
ifOnly   Same as "ifFirst" above, but sub-style will be applied to the item if it is the only one, i.e. it's parent has no other items.
ifSeparator   Same as "ifFirst" above, but sub-style will be applied to the item if it has no "code" field defined, i.e. if it is separator item.

* "State aware" property set to "Yes" indicates that field can accept scalar or array value. E.g. textClass:'cssClass' means that text will have class="cssClass" attribute in both states, and textClass['cssClass1','cssClass2'] means that text will have class="cssClass1" in normal state and class="cssClass2" in rollovered state.

** For more information on filters and transitions, please read this article at MSDN: Introduction to Filters and Transitions.


All colors can be specified as #XXXXXX (where X is hexadecimal digit) or as color name (red, green, blue, etc.).

Structure definition

Generally, menu structure definition looks like the following:

var MENU_ITEMS = [
    { pos:'relative', leveloff:[b,a], itemoff:[d,c], size:[e,f], ... },
    { ...Item 1... },
    { ...Item 2... ,
        sub:[
            { ...level format... },
            { ...Item 1... },
            { ...Item 2... },
            { ...Item 3... ,
                sub:[
                    { ...level format... },
                    { ...Item 1... },
                    { ...Item 2... },
                    { ...Item 3... },
                    { ...Item 4... }
                ]
            },
            { ...Item 4... },
        ]
    },
    { ...Item 3... }
];

Instead of "...level format..." style definition fields can be used (with exception of "if*" fields). Also, "style" field is available:

Name Description
style Assigns style to item and all subitems. Also, array of styles can be used, e.g. instead of this:
var MENU_ITEMS = [
    {..., style:STYLE1, ...}
    {code:'Item',
        sub:[
            {style:STYLE2},
            {code:'Sub-item',
                sub:[
                    {style:STYLE3},
                    {code:'Sub-sub-item',
                    }
                ]
            }
        ]
    }
];
One can write this:
var MENU_ITEMS = [
    {..., style:[STYLE1, STYLE2, STYLE3], ...}
    {code:'Item',
        sub:[
            {},
            {code:'Sub-item',
                sub:[
                    {},
                    {code:'Sub-sub-item',
                    }
                ]
            }
        ]
    }
];

Root level also can have these additional fields:

Name Description
dynamic If set to false, all needed HTML will be pre-created during menu initialization. Because of this initialization can take more time (much more if the menu is large), but there will be less delays when sublevels are being shown for the very first time. Defaults to true.
zIndex Least z-index value to be used by menu. Helps to combine menus with other scripts. Defaults to 1000.
exclusive When one rollovers the menu, all other menus (if any) on the page will be collapsed. Defaults to true.
delay Sets rollover and rollout delays delays. Defaults to [0, 800]. To assign equal delays for both rollover and rollout, one can use single number:
var MENU_ITEMS = [
    {..., delay:400, ...}
    ...
For more comfortable feel, we'd recommend following values:
var MENU_ITEMS = [
    {..., delay:[100,800], ...}
    ...
pos Specifies coordinates (x, y) where the menu will be created:
var MENU_ITEMS = [
    {pos:[10,20], ...}
    ...
Professional edition also supports special value 'relative', i.e. menu will be placed into position where the initialization was done (initTop call):
var MENU_ITEMS = [
    {pos:'relative', ...}
    ...
Defaults to [0, 0] for Standard edition and to 'relative' for Professional edition.
popup Professional only: popup menus must have "popup" field set to "1" or "true". Working sample with additional information is here.
frames Professional edition only. If presents, menu will work in cross-frame mode.
var MENU_ITEMS = [
    {..., frames:['topFrameName','bottomFrameName'], ...}
    ...
Working sample with additional information can be found in the Professional package.
imagePrefix All images (i.e. defined by "image", "arrow", "blankImage" fields) will have this prefix. So, if menu definition is like the following:
var MENU_ITEMS = [
    {..., imagePrefix:'/special/images/', ...}
    {code:'Item 1', image:'ico1.gif', ...}
    ...
then actual image will be equivalent to the following:
<img src="/special/images/ico1.gif" ... />
Defaults to empty string.
urlPrefix All URLs (i.e. defined by "url" field) will have this prefix. So, if menu definition is like the following:
var MENU_ITEMS = [
    {..., urlPrefix:'http://www.otherdomain.com/subdir/', ...}
    {code:'Item 1', url:'file.html', ...}
    ...
then actual link will be equivalent to the following:
<a href="http://www.otherdomain.com/subdir/file.hrml" ...>...</a>
Defaults to empty string.
blankImage Menu needs blank 1x1 GIF image for internal purposes, and this field contains path to this image. For compatibility purposes default value is BLANK_IMAGE global variable's value - 'img/b.gif'. Note: this field is not defined (i.e. if BLANK_IMAGE value is used), then imagePrefix does not apply to it's value.
clickToActivate If set to true, menu will not show any sublevels until the first click. This behavior is similar to what one can observe in applications' menus. Defaults to false.

All these values are inherited "in depth", i.e. if submenu defines style and size of it's items, then all submenus recursively will have items with same style and size, unless specified otherwise.

Every item can contain any style definition field (with exception of "if*" fields). Also, following fields are allowed:

Name State aware? Description
code Yes "code" contains item's caption for normal state, and "ocode" - for rollovered state. Almost any HTML code can be used here, but only simple formatting instructions (DIV and SPAN with "class" or "style" attributes, B, I, U, etc.) and images will be useful enough. If "ocode" is ommited, "code" will be used for rollovered state.
ocode   Obsolete way to use "code".
url   Associates URL with item. Fully compatible with <a href="..."> (including "javascript:" protocol).
target   Specifies optional target frame, same as <a target="...">.
format   Obsolete. Now older definition like in the following sample
{code:'Item 1', format:{image:'images/icon.gif', imgsize:[15,15]}, ...
can be written like this:
{code:'Item 1', image:'images/icon.gif', imgsize:[15,15], ...
sub  

Defines submenu, e.g.:

{code:'Item with submenu',
    sub:[
        {style:SOME_STYLE},
        {code:'Item 1'},
        {code:'Item 2'}
    ]
},
hasControls  

Professional only: allows to use form controls as content for the item, e.g.:

{
    code:'Some memo:<br /><textarea></textarea>',
    hasControls:true,
    format:{size:[78,170]}
},

When this attribute presents, menu behaves differently: it will allow you to focus control without hiding itself. Also, "ocode" attribute will not work for items with "hasControls" set to "true".

Copyright © CoolDev.Com 1997-2007.